package storage

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"goDFS/etc"
	"goDFS/public"
	"goDFS/requests"
	"net/http"
	"time"
)

//这里定义了文件服务器
var Conf *etc.Conf
var Address string

//注册文件服务到tracker
func registerTracker(ip string, port int, conf *etc.Conf) error {
	trackerConf := conf.GetTracker()
	url := fmt.Sprintf("http://%s:%d%s",
		trackerConf.Host, trackerConf.Port, public.RegisterApi)

	parm := map[string]string{
		"ip":   ip,
		"port": fmt.Sprintf("%d", port),
	}

	ticker := time.NewTicker(time.Second * 60 * 10) //每10分钟重新注册一下状态

	cline := requests.NewHttpSend(requests.GetUrlBuild(url, parm))
	cline.Get()

	go func() {
		for true {
			select {
			case <-ticker.C:
				_, err := cline.Get()
				if err != nil {
					fmt.Println(err)
				}
			}
		}

		//处理ticker
		ticker.Stop()
	}()

	return nil

}

//获取一个可以用的端口

// 处理跨域请求,支持options访问
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method

		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		c.Header("Access-Control-Allow-Credentials", "true")

		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

//开始服务，监听入口
func Service(conf *etc.Conf) {

	Conf = conf
	etc.CreatLogFile(Conf.GetStorage())
	//随机获取ip
	ip, err := public.GetIPv4s()
	if err != nil {
		etc.SaveLog("[ Storage_Service ]"+err.Error(), 2)
		return
	}

	port, err := public.GetAvailablePort()
	if err != nil {
		etc.SaveLog("[ Storage_Service ]"+err.Error(), 2)
		return
	}

	addr := fmt.Sprintf("%s:%d", ip, port)
	Address = addr

	//初始化注册服务
	registerTracker(ip.String(), port, conf)

	server := gin.Default()
	server.Use(Cors())
	//接口
	{
		server.MaxMultipartMemory = 10 << 20 //最大10mb文件
		server.POST(UploadApi, UpLoad)       //上传接口
		server.GET(GetApi, GetFile)          //下载接口
		server.GET(HeartbeatApi, Heartbeat)
		server.GET(public.SyncFileApi, ToSyncFile)
	}

	server.Run(addr)

}
